<template>
  <div>
    <input type="file" @change="handleFileChange" />
    <el-button @click="uploadChunks"> 上传 </el-button>
    <!-- <el-button @click="pauseUpload"> 暂停 </el-button> -->
    <div style="width: 300px">
          总进度：
          <el-progress :percentage="tempPercent"></el-progress>
          切片进度：
          <div v-for="(item,index) in fileObj.chunkList" :key="index">
            <span>{{ item.chunkName }}：</span>
            <el-progress :percentage="item.percent"></el-progress>
          </div>
    </div>
  </div>
</template>

<script>
import axios from "axios";
import md5 from 'js-md5'
 const CancelToken = axios.CancelToken;
 let source = CancelToken.source();

function axiosRequest({
  url,
  method = "post",
  data,
  headers = {},
  onUploadProgress = (e) => e, // 进度回调
}) {
  return new Promise((resolve, reject) => {
    axios[method](url, data, {
      headers,
      onUploadProgress, // 传入监听进度回调
      cancelToken: source.token
    })
      .then((res) => {
        resolve(res);
      })
      .catch((err) => {
        reject(err);
      });
  });
}
export default {
  data() {
    return {
      fileObj: {
        file: null,
        chunkList:[]
      },
      tempPercent:0
    };
  },
  methods: {
    handleFileChange(e) {
      const [file] = e.target.files;
      if (!file) return;
      this.fileObj.file = file;
      const fileObj = this.fileObj;
      if (!fileObj.file) return;
      const chunkList = this.createChunk(fileObj.file);
      console.log(chunkList); // 看看chunkList长什么样子
      let that = this
      // 获取此视频的哈希值,作为名字
      let fileReader = new FileReader();
      fileReader.readAsDataURL(e.target.files[0]);
      fileReader.onload = function (e2) {
          const hexHash = md5(e2.target.result)+'.'+that.fileObj.file.name.split('.').pop();
          that.fileObj.name = hexHash
          that.fileObj.chunkList = chunkList.map(({ file }, index) => ({
          file,
          size: file.size,
          percent: 0,
          chunkName: `${hexHash}-${index}`,
          fileName: hexHash,
          index,
        }))
      };
    },
    createChunk(file, size = 512 * 1024) {
      const chunkList = [];
      let cur = 0;
      while (cur < file.size) {
        // 使用slice方法切片
        chunkList.push({ file: file.slice(cur, cur + size) });
        cur += size;
      }
      return chunkList;
    },
    async uploadChunks() {
      const {uploadedList,shouldUpload} = await this.verifyUpload()
      // 如果存在这个文件
      if(!shouldUpload){
        console.log('秒传成功')
        this.fileObj.chunkList.forEach(item => {
          item.percent = 100
        });
        return 
      }
      let noUploadChunks = []
      if(uploadedList&&uploadedList.length>0 &&uploadedList.length !== this.fileObj.chunkList.length){
        // 如果存在切片。只上传没有的切片
        noUploadChunks =  this.fileObj.chunkList.filter(item=>{
          if(uploadedList.includes(item.chunkName)){
            item.percent = 100
          }
          return !uploadedList.includes(item.chunkName)
        })
      }else{
        noUploadChunks = this.fileObj.chunkList
      }
      const requestList = noUploadChunks.map(({ file, fileName, index, chunkName }) => {
          const formData = new FormData();
          formData.append("file", file);
          formData.append("fileName", fileName);
          formData.append("chunkName", chunkName);
          return { formData, index };
        })
        .map(({ formData, index }) =>
          axiosRequest({
            url: "http://localhost:3000/upload",
            data: formData,
            onUploadProgress: this.createProgressHandler(
              this.fileObj.chunkList[index]
            ), // 传入监听上传进度回调
          })
        );
      await Promise.all(requestList); // 使用Promise.all进行请求
      this.mergeChunks()
    },
    createProgressHandler(item) {
      return (e) => {
        // 设置每一个切片的进度百分比
        item.percent = parseInt(String((e.loaded / e.total) * 100));
      };
    },
    mergeChunks(size = 512 * 1024) {
      axiosRequest({
         url: "http://localhost:3000/merge",
         headers: {
           "content-type": "application/json",
         },
         data: JSON.stringify({ 
          size,
           fileName: this.fileObj.name
         }),
       });
     },
     pauseUpload() {
      source.cancel("中断上传!");
       source = CancelToken.source(); // 重置source，确保能续传
     },
     async verifyUpload () {
       const { data } = await axiosRequest({
         url: "http://localhost:3000/verify",
         headers: {
           "content-type": "application/json",
         },
         data: JSON.stringify({
           fileName:this.fileObj.name
        }),
      });
      return data
     }
  },
  computed: {
    totalPercent() {
      const fileObj = this.fileObj;
      if (fileObj.chunkList.length === 0) return 0;
      const loaded = fileObj.chunkList
        .map(({ size, percent }) => size * percent)
       .reduce((pre, next) => pre + next);
      return parseInt((loaded / fileObj.file.size).toFixed(2));
    },
  },
  watch: {
      totalPercent (newVal) {
           if (newVal > this.tempPercent) this.tempPercent = newVal
       }
   },
};
</script>

<style lang="scss" scoped></style>
